
#pragma once

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

#include <iostream>

using namespace cv;

namespace course_07_shape_detection
{

    void getContours(Mat imgDia, Mat image)
    {

        std::vector<std::vector<Point>> contours;
        std::vector<Vec4i> hierarchy;
        //找到边缘
        findContours(imgDia, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
        //位置边缘轮廓
        drawContours(image, contours, -1, Scalar(255, 100, 255), 1);

        std::vector<std::vector<Point>> conPoly(contours.size());
        std::vector<Rect> boundRect(contours.size());

        std::string objectType;
        //计算边界轮廓内面积大小  可用于降噪
        for (int i = 0; i < contours.size(); i++)
        {
            //计算边界轮廓内面积大小
            int area = contourArea(contours[i]);
            std::cout << "Area: " << area << std::endl;

            //根据轮廓形状绘制多边形
            float peri = arcLength(contours[i], true);
            approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);
            drawContours(image, conPoly, i, Scalar(255, 100, 255), 2);
            std::cout << "conPoly-size: " << conPoly.size() << std::endl;

            //绘制轮廓形状的外包络矩形
            boundRect[i] = boundingRect(conPoly[i]);
            rectangle(image, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);

            //根据角点数量判断形状
            int objCorner = (int)conPoly[i].size();
            if (objCorner == 3)
            {
                objectType = "Triangle";
            }
            if (objCorner == 4)
            {
                objectType = "Rectangle";
            }
            if (objCorner > 4)
            {
                objectType = "Circle or Polygon";
            }
            //写上判断结果
            putText(image, objectType, {boundRect[i].x, boundRect[i].y - 5}, FONT_HERSHEY_DUPLEX, 0.75, Scalar(0, 211, 311), 1);
        }
    }

    void shape_detection(std::string path)
    {
        Mat image = imread(path);

        Mat imageGray, imageBlur, imgCanny, imgDia;

        cvtColor(image, imageGray, COLOR_BGR2GRAY);
        GaussianBlur(image, imageBlur, Size(7, 7), 5, 5); //高斯模糊
        Canny(imageBlur, imgCanny, 50, 150);
        Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
        dilate(imgCanny, imgDia, kernel);

        getContours(imgDia, image);

        imshow("IMAGE", image);
        imshow("IMAGE-Gray", imageGray);
        imshow("IMAGE-blur", imageBlur);
        imshow("IMAGE-canny", imgCanny);
        imshow("IMAGE-dila", imgDia);

        waitKey(0);
    }
}